﻿/************************************************************************

 This file is part of EscapeFromPrisonPlanet.

 EscapeFromPrisonPlanet is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 EscapeFromPrisonPlanet is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2012 Scott Bevin. all rights reserved

using System;
using System.Collections.Generic;
using LudumDare25Project.Objects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace LudumDare25Project.GameScreens
{
	internal class GameplayScreen : GameScreen
	{
		private bool debugMode = false;

		private float speedMod = 4.0f;

		private Camera camera;
		private Spaceship playerShip;
		private StarryBackground background;
		private AsteroidBelt topBelt;
		private AsteroidBelt botBelt;
		private HUD hud;
		private Texture2D bulletTex;
		private Texture2D missileTex;
		private Texture2D prisonPlanet;
		private float ppScale = 1.0f;
		private Vector2 ppPos = new Vector2(200.0f, 400.0f);

		private Texture2D enemyShipTex;
		private Texture2D enemyShip2Tex;

		private Texture2D target;
		private float targetRot = 0.0f;
		private Vector2 targetPos = Vector2.Zero;
		private bool shouldRenderTarget = false;

		private float score = 0.0f;

		private float Difficulty { get { return 1.0f + (score * 0.005f); } }

		private WhiteFadeScreen whiteFadeOut = null;

		private Texture2D[] PickupTexture = new Texture2D[(int)Pickup.Types.Max];

		private List<Bullet> bullets = new List<Bullet>();
		private List<Bullet> enemyBullets = new List<Bullet>();
		private List<Missile> missiles = new List<Missile>();
		private List<Spaceship> enemyShips = new List<Spaceship>();
		private List<Pickup> pickups = new List<Pickup>();

		private ExplosionSys explostions;

		// Sound effects
		private List<SoundEffect> explosionSfxs = new List<SoundEffect>();

		private SoundEffect fireMissileSfx;
		private SoundEffect fireGunSfx;
		private SoundEffect hPickupSfx;
		private SoundEffect mPickupSfx;
		private SoundEffect sPickupSfx;
		private SoundEffect useShieldSfx;
		private SoundEffect takeHitSfx;
		private SoundEffect bulletHitAsteroidSFX;

		public GameplayScreen()
			: base(true)
		{
		}

		public override void OnAdded()
		{
			this.Game.IsMouseVisible = false;

			SetupPlayerShip();

			prisonPlanet = ContentManager.Load<Texture2D>("Img/Planets/HomePlanet");
			enemyShipTex = ContentManager.Load<Texture2D>("Img/Ships/EnemyShip1");
			enemyShip2Tex = ContentManager.Load<Texture2D>("Img/Ships/EnemyShip2");
			target = ContentManager.Load<Texture2D>("Img/Target");
			bulletTex = ContentManager.Load<Texture2D>("Img/Bullet");
			missileTex = ContentManager.Load<Texture2D>("Img/Missile");

			LoadExplosionSfxs();
			fireMissileSfx = ContentManager.Load<SoundEffect>("Sfx/FireMissile");
			fireGunSfx = ContentManager.Load<SoundEffect>("Sfx/ShootGun1");
			hPickupSfx = ContentManager.Load<SoundEffect>("Sfx/Pickup1");
			mPickupSfx = ContentManager.Load<SoundEffect>("Sfx/Pickup2");
			sPickupSfx = ContentManager.Load<SoundEffect>("Sfx/Pickup3");
			useShieldSfx = ContentManager.Load<SoundEffect>("Sfx/UseShield");
			takeHitSfx = ContentManager.Load<SoundEffect>("Sfx/TakeHit1");
			bulletHitAsteroidSFX = ContentManager.Load<SoundEffect>("Sfx/BulletHitAsteroid");

			PickupTexture[(int)Pickup.Types.Health] = ContentManager.Load<Texture2D>("Img/Pickups/Health");
			PickupTexture[(int)Pickup.Types.Missiles] = ContentManager.Load<Texture2D>("Img/Pickups/Missiles");
			PickupTexture[(int)Pickup.Types.Shield] = ContentManager.Load<Texture2D>("Img/Pickups/Shields");
			PickupTexture[(int)Pickup.Types.Bomb] = ContentManager.Load<Texture2D>("Img/Pickups/Bomb");

			camera = new Camera(Game.GraphicsDevice.PresentationParameters.BackBufferWidth, Game.GraphicsDevice.PresentationParameters.BackBufferHeight);
			camera.Position = camera.TargetPosition = playerShip.Position;

			background = new StarryBackground(this.ContentManager, new Vector2(Game.GraphicsDevice.PresentationParameters.BackBufferWidth, Game.GraphicsDevice.PresentationParameters.BackBufferHeight));

			topBelt = new AsteroidBelt(this.ContentManager, 700.0f, (float)Game.GraphicsDevice.PresentationParameters.BackBufferWidth, 1.0f);
			botBelt = new AsteroidBelt(this.ContentManager, -700.0f, (float)Game.GraphicsDevice.PresentationParameters.BackBufferWidth, -1.0f);

			hud = new HUD(playerShip, ContentManager);

			explostions = new ExplosionSys(ContentManager);

			base.OnAdded();
		}

		public override void OnRemoved()
		{
			this.Game.IsMouseVisible = true;

			base.OnRemoved();
		}

		private void LoadExplosionSfxs()
		{
			bool done = false;
			int counter = 1;

			while (!done)
			{
				try
				{
					SoundEffect tex = ContentManager.Load<SoundEffect>("Sfx/Explosion" + counter.ToString());
					explosionSfxs.Add(tex);
					counter++;
				}
				catch (Exception e)
				{
					done = true;
				}
			}
		}

		public override void Update(float dt, InputManager input)
		{
			this.Game.IsMouseVisible = !TopMostScreen;

			if (TopMostScreen)
			{
				if (input.KeyStates[(int)Keys.Escape].Pressed)
				{
					GameScreenManager.AddGameScreen(new PauseScreen(this), null, LudumDare25Project.GameScreenManager.AddGameScreenData.PositioningOptions.OnTop);
				}

#if DEBUG
				debugMode = input.KeyStates[(int)Keys.X].Down;
#endif

				score += dt * speedMod;
				ppScale -= (0.05f * dt);
				ppScale = Math.Max(ppScale, 0.1f);
				ppPos += (new Vector2(-5.0f, 5.0f) * dt);

				targetRot += dt;

				ProcessPlayer(dt, input);
			}

			ProcessCamera(dt);

			if (TopMostScreen)
			{
				background.Update(dt * speedMod, playerShip.Position, camera);

				topBelt.Update(dt, camera.Position.X, speedMod);
				botBelt.Update(dt, camera.Position.X, speedMod);

				ProcessAsteroids(dt);
				ProcessEnemySpaceships(dt);
				ProcessBullets(dt);
				ProcessEnemyBullets(dt);
				ProcessMissiles(dt);
				ProcessPickups(dt);
			}

			explostions.Update(dt);

			if (!debugMode)
				ProcessGameOver();

			PickCursorTarget(input);

			base.Update(dt, input);
		}

		private void ProcessPickups(float dt)
		{
			for (int i = 0; i < pickups.Count; )
			{
				pickups[i].Update(dt * speedMod * 0.5f);

				bool kill = (pickups[i].Position.X < camera.Position.X - 1000.0f);

				if ((playerShip.Position - pickups[i].Position).LengthSquared() <
					(pickups[i].Radius + playerShip.Radius) * (pickups[i].Radius + playerShip.Radius))
				{
					kill = true;

					if (pickups[i].Type == Pickup.Types.Health)
					{
						playerShip.HullHealth += 20.0f;
						playerShip.HullHealth = Math.Min(playerShip.HullHealth, 100.0f);
						hPickupSfx.Play();
					}
					else if (pickups[i].Type == Pickup.Types.Missiles)
					{
						playerShip.Missiles = Spaceship.MaxMissiles;
						mPickupSfx.Play();
					}
					else if (pickups[i].Type == Pickup.Types.Shield)
					{
						playerShip.Shield += 20.0f;
						playerShip.Shield = Math.Min(playerShip.Shield, 100.0f);
						sPickupSfx.Play();
					}
					else if (pickups[i].Type == Pickup.Types.Bomb)
					{
						takeHitSfx.Play();
						playerShip.HullHealth -= 50.0f;
						explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
						explostions.AddExplosion(pickups[i].Position);
					}
				}

				if (kill)
					pickups.RemoveAt(i);
				else
					++i;
			}
		}

		private float timeTillNextShip = 7.5f;
		private float timeTillNextShipWall = 15.0f;

		private void ProcessEnemySpaceships(float dt)
		{
			timeTillNextShipWall -= dt;

			if ((timeTillNextShip -= dt) <= 0.0f)
			{
				timeTillNextShip = 3.5f / Difficulty;

				if (timeTillNextShipWall <= 0.0f)
				{
					timeTillNextShipWall = 30.0f / Difficulty;

					for (int i = 0; i < 10; ++i)
					{
						bool wavy = (rnd.Next(100) < 50);

						Spaceship newShip = new Spaceship(ContentManager, wavy ? enemyShip2Tex : enemyShipTex, null,
							wavy ? new Vector2(100.0f, 15.0f) : new Vector2(103.0f, 5.0f));
						newShip.Position = new Vector2(camera.Position.X + 1000.0f, RandomFloat(-600.0f, 600.0f));
						newShip.velocity = new Vector2(RandomFloat(-600.0f, -300.0f), 0.0f);
						newShip.HullHealth = 3;

						enemyShips.Add(newShip);
					}
				}
				else
				{
					bool wavy = (rnd.Next(100) < 50);

					Spaceship newShip = new Spaceship(ContentManager, wavy ? enemyShip2Tex : enemyShipTex, null,
						wavy ? new Vector2(100.0f, 15.0f) : new Vector2(103.0f, 5.0f));

					//newShip.Wavy = wavy;
					newShip.Position = new Vector2(camera.Position.X + 1000.0f, RandomFloat(-600.0f, 600.0f));
					newShip.velocity = new Vector2(RandomFloat(-600.0f, -300.0f), 0.0f);
					newShip.HullHealth = 3;

					enemyShips.Add(newShip);
				}
			}

			for (int i = 0; i < enemyShips.Count; )
			{
				enemyShips[i].Update(dt * speedMod * 0.3f);

				bool kill = (enemyShips[i].Position.X < camera.Position.X - 1000.0f);

				if ((playerShip.Position - enemyShips[i].Position).LengthSquared() <
					(enemyShips[i].Radius + playerShip.Radius) * (enemyShips[i].Radius + playerShip.Radius))
				{
					kill = true;

					explostions.AddExplosion(enemyShips[i].Position);
					explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();

					if (playerShip.Invulnerable <= 0.0f && !playerShip.ShieldActive)
					{
						takeHitSfx.Play();
						playerShip.HullHealth -= 10.0f;
						playerShip.Invulnerable = 0.25f;
						speedMod = 4.0f;
					}
				}

				if (kill)
					enemyShips.RemoveAt(i);
				else
					++i;
			}
		}

		private void ProcessAddingPickup(Vector2 pos)
		{
			if (rnd.Next(0, 100) < 10)
			{
				int type = rnd.Next(0, (int)Pickup.Types.Max);

				Pickup p = new Pickup((Pickup.Types)type, PickupTexture[type]);
				p.Position = pos;
				pickups.Add(p);
			}
		}

		private void ProcessMissiles(float dt)
		{
			for (int i = 0; i < missiles.Count; )
			{
				missiles[i].Update(dt, camera.Position.X);

				for (int j = 0; j < asteroids.Count; )
				{
					if ((asteroids[j].Position - missiles[i].Position).LengthSquared() <
						(missiles[i].Radius + asteroids[j].Radius) * (missiles[i].Radius + asteroids[j].Radius))
					{
						missiles[i].Kill = true;
						explostions.AddExplosion(asteroids[j].Position);
						explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
						asteroids.RemoveAt(j);
					}
					else
					{
						++j;
					}
				}

				for (int j = 0; j < enemyShips.Count; )
				{
					if ((enemyShips[j].Position - missiles[i].Position).LengthSquared() <
						(missiles[i].Radius + enemyShips[j].Radius) * (missiles[i].Radius + enemyShips[j].Radius))
					{
						missiles[i].Kill = true;

						ProcessAddingPickup(enemyShips[j].Position);
						explostions.AddExplosion(enemyShips[j].Position);
						explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
						enemyShips.RemoveAt(j);
					}
					else
					{
						++j;
					}
				}

				if (missiles[i].Kill)
				{
					KillAllInRange(missiles[i].Position, 250.0f);
					missiles.RemoveAt(i);
				}
				else
					++i;
			}
		}

		private void ProcessBullets(float dt)
		{
			for (int i = 0; i < bullets.Count; )
			{
				bullets[i].Update(dt, camera.Position.X);

				foreach (AsteroidBelt.Asteroid ast in asteroids)
				{
					if ((ast.Position - bullets[i].Position).LengthSquared() <
						(bullets[i].Radius + ast.Radius) * (bullets[i].Radius + ast.Radius))
					{
						bulletHitAsteroidSFX.Play();
						bullets[i].Kill = true;
					}
				}

				for (int j = 0; j < enemyShips.Count; )
				{
					if ((enemyShips[j].Position - bullets[i].Position).LengthSquared() <
						(bullets[i].Radius + enemyShips[j].Radius) * (bullets[i].Radius + enemyShips[j].Radius))
					{
						bullets[i].Kill = true;

						enemyShips[j].HullHealth--;
						takeHitSfx.Play();

						if (enemyShips[j].HullHealth <= 0)
						{
							ProcessAddingPickup(enemyShips[j].Position);
							explostions.AddExplosion(enemyShips[j].Position);
							explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
							enemyShips.RemoveAt(j);
						}
						else
							++j;
					}
					else
					{
						++j;
					}
				}

				if (bullets[i].Kill)
					bullets.RemoveAt(i);
				else
					++i;
			}
		}

		private void ProcessEnemyBullets(float dt)
		{
			for (int j = 0; j < enemyShips.Count; ++j)
			{
				if ((enemyShips[j].enemyShootTimer -= dt) < 0.0f)
				{
					enemyShips[j].enemyShootTimer = RandomFloat(2.5f, 4.5f) / Difficulty;

					Bullet newBullet = new Bullet(bulletTex, enemyShips[j].Position,

						// (rnd.Next(100) < 25 && enemyShips[j].Position.X > playerShip.Position.X + 300.0f) ? playerShip.Position : enemyShips[j].Position + new Vector2(-1000.0f, 0.0f),

					   enemyShips[j].Position + enemyShips[j].velocity, Color.Red);

					fireGunSfx.Play();

					newBullet.Velocity *= 0.25f;

					enemyBullets.Add(newBullet);
				}
			}

			for (int i = 0; i < enemyBullets.Count; )
			{
				enemyBullets[i].Update(dt * speedMod, camera.Position.X);

				foreach (AsteroidBelt.Asteroid ast in asteroids)
				{
					if ((ast.Position - enemyBullets[i].Position).LengthSquared() <
						(enemyBullets[i].Radius + ast.Radius) * (enemyBullets[i].Radius + ast.Radius))
					{
						bulletHitAsteroidSFX.Play();
						enemyBullets[i].Kill = true;
					}
				}

				if (!playerShip.ShieldActive && playerShip.Invulnerable <= 0.0f)
				{
					if ((playerShip.Position - enemyBullets[i].Position).LengthSquared() <
							(enemyBullets[i].Radius + playerShip.Radius) * (enemyBullets[i].Radius + playerShip.Radius))
					{
						enemyBullets[i].Kill = true;

						playerShip.Invulnerable = 0.05f;
						playerShip.HullHealth--;

						takeHitSfx.Play();
					}
				}

				if (enemyBullets[i].Kill)
					enemyBullets.RemoveAt(i);
				else
					++i;
			}
		}

		private float timerForNewBullet = 0.0f;

		private void ProcessPlayer(float dt, InputManager input)
		{
			float targSpeedMod = speedMod;

			if (input.KeyStates[(int)Keys.A].Down || input.KeyStates[(int)Keys.Left].Down)
				targSpeedMod = 4.0f;
			else if (input.KeyStates[(int)Keys.D].Down || input.KeyStates[(int)Keys.Right].Down)
				targSpeedMod = 10.0f;

			Vector2 mousePos = camera.ScreenToWorld(input.CurrentMousePos);

			if ((timerForNewBullet -= dt) < 0.0f && playerShip.Ammo > 0)
			{
				if (input.MouseButtonStates[(int)InputManager.MouseButtons.LeftButton].Down)
				{
					timerForNewBullet = 0.1f;

					//playerShip.Ammo--;
					fireGunSfx.Play();
					bullets.Add(new Bullet(bulletTex, playerShip.Position + new Vector2(40.0f, 40.0f), mousePos, Color.Green));
				}
			}

			if (input.MouseButtonStates[(int)InputManager.MouseButtons.RightButton].Released &&
				playerShip.Missiles > 0)
			{
				playerShip.Missiles--;
				fireMissileSfx.Play();
				missiles.Add(new Missile(ContentManager, missileTex, playerShip.Position + new Vector2(40.0f, 40.0f), mousePos));
			}

			bool shieldWasActive = playerShip.ShieldActive;
			playerShip.ShieldActive = false;

			if (input.KeyStates[(int)Keys.Space].ThisFrame && playerShip.Shield > 0.0f)
			{
				if (!shieldWasActive)
					useShieldSfx.Play();

				playerShip.ShieldActive = true;
				playerShip.Shield -= (dt * 10.0f);
			}

			speedMod += ((targSpeedMod - speedMod) * dt);

			if (debugMode)
				speedMod = 0.01f;

			playerShip.HandleInput(input, camera);
			playerShip.Update(dt);

			if (playerShip.Position.Y < -700.0f)
			{
				playerShip.velocity.Y = 500.0f;

				if (playerShip.Invulnerable <= 0.0f)
				{
					if (!playerShip.ShieldActive)
					{
						playerShip.HullHealth -= 10.0f;
						takeHitSfx.Play();
					}

					playerShip.Invulnerable = 0.25f;
					speedMod = 4.0f;
				}
			}

			if (playerShip.Position.Y > 700.0f)
			{
				playerShip.velocity.Y = -500.0f;

				if (playerShip.Invulnerable <= 0.0f)
				{
					if (!playerShip.ShieldActive)
					{
						playerShip.HullHealth -= 10.0f;
						takeHitSfx.Play();
					}

					playerShip.Invulnerable = 0.25f;
					speedMod = 4.0f;
				}
			}

#if DEBUG
			DebugDraw.Get.AddText("Player - Pos: " + playerShip.Position.ToString());
			DebugDraw.Get.AddText("Player - HP: " + playerShip.HullHealth);
			DebugDraw.Get.AddText("Player - Ammo: " + playerShip.Ammo);
			DebugDraw.Get.AddText("Player - Shield: " + playerShip.Shield + playerShip.ShieldActive.ToString());
			DebugDraw.Get.AddText("Speed Mod: " + speedMod.ToString());
#endif
		}

		private void ProcessCamera(float dt)
		{
			camera.TargetPosition = playerShip.Position;
			camera.TargetPosition.X += 750.0f;

			camera.Update(dt);
		}

		public override void Render(float dt, Microsoft.Xna.Framework.Graphics.GraphicsDevice gd, Microsoft.Xna.Framework.Graphics.SpriteBatch sprites)
		{
			background.Render(sprites, camera);

			sprites.Begin();
			sprites.Draw(prisonPlanet, ppPos, null, Color.White, 0.0f,
				new Vector2(prisonPlanet.Width, prisonPlanet.Height) * 0.5f, ppScale, SpriteEffects.None, 0.0f);
			sprites.End();

			sprites.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default,
				RasterizerState.CullNone, null, camera.GetWorldMatrix());

			foreach (Bullet bullet in bullets)
			{
				bullet.Render(sprites);
			}

			foreach (Bullet bullet in enemyBullets)
			{
				bullet.Render(sprites);
			}

			foreach (Missile missile in missiles)
			{
				missile.Render(sprites);
			}

			if (playerShip.HullHealth > 0)
				playerShip.Render(sprites);

			foreach (Spaceship ship in enemyShips)
			{
				ship.Render(sprites);
			}

			foreach (Pickup pickup in pickups)
			{
				pickup.Render(sprites);
			}

			topBelt.Render(sprites);
			botBelt.Render(sprites);

			foreach (AsteroidBelt.Asteroid ast in asteroids)
			{
				sprites.Draw(
					ast.Sprite,
					ast.Position,
					null,
					Color.White,
					ast.Rotation,
					new Vector2(ast.Sprite.Width, ast.Sprite.Height) * 0.5f,
					ast.Scale,
					SpriteEffects.None,
					0.0f);
			}

			explostions.Render(sprites);

			if (shouldRenderTarget)
				RenderTarget(sprites, targetPos);

			sprites.End();

			hud.Render(sprites, score);

			base.Render(dt, gd, sprites);
		}

		private void PickCursorTarget(InputManager input)
		{
			Vector2 mousePos = camera.ScreenToWorld(input.CurrentMousePos);

			shouldRenderTarget = true;
			targetPos = mousePos;

			foreach (AsteroidBelt.Asteroid ast in asteroids)
			{
				if ((ast.Position - mousePos).LengthSquared() < (ast.Radius * ast.Radius))
				{
					shouldRenderTarget = true;
					targetPos = ast.Position;

					return;
				}
			}

			foreach (Spaceship ship in enemyShips)
			{
				if ((ship.Position - mousePos).LengthSquared() < (ship.Radius * ship.Radius))
				{
					shouldRenderTarget = true;
					targetPos = ship.Position;

					return;
				}
			}

			foreach (Pickup pu in pickups)
			{
				if ((pu.Position - mousePos).LengthSquared() < (pu.Radius * pu.Radius))
				{
					shouldRenderTarget = true;
					targetPos = pu.Position;

					return;
				}
			}
		}

		private void RenderTarget(SpriteBatch sprites, Vector2 pos)
		{
			sprites.Draw(target, pos, null, Color.White, targetRot,
				new Vector2(target.Width, target.Height) * 0.5f, 1.0f, SpriteEffects.None, 0.0f);
		}

		private void SetupPlayerShip()
		{
			playerShip = new Spaceship(ContentManager, ContentManager.Load<Texture2D>("Img/Ships/PT1"),
				ContentManager.Load<Texture2D>("Img/Ships/PT1Shield"), new Vector2(-128.0f, 15.0f));
			playerShip.Position = Vector2.Zero;
		}

		private void ProcessGameOver()
		{
			if (playerShip.HullHealth <= 0.0f)
			{
				if (whiteFadeOut == null)
				{
					explostions.AddExplosion(playerShip.Position);
					explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();

					whiteFadeOut = new WhiteFadeScreen();

					GameScreenManager.AddGameScreen(whiteFadeOut, null, LudumDare25Project.GameScreenManager.AddGameScreenData.PositioningOptions.OnTop);
				}

				if (whiteFadeOut != null && whiteFadeOut.State == WhiteFadeScreen.States.FadedIn)
				{
					whiteFadeOut.FadeOut();
					GameScreenManager.AddGameScreen(new GameOverScreen(score), whiteFadeOut, LudumDare25Project.GameScreenManager.AddGameScreenData.PositioningOptions.BelowRef);
					this.KillScreen = true;
				}
			}
		}

		private float timeTillNextAsteroid = 5.0f;
		private List<AsteroidBelt.Asteroid> asteroids = new List<AsteroidBelt.Asteroid>();

		private float timeTillNextAsteroidWall = 5.0f;

		private void ProcessAsteroids(float dt)
		{
			timeTillNextAsteroidWall -= dt;

			if ((timeTillNextAsteroid -= dt) <= 0.0f)
			{
				timeTillNextAsteroid = 5.0f / Difficulty;

				if (timeTillNextAsteroidWall <= 0.0f)
				{
					timeTillNextAsteroidWall = 30.0f / Difficulty;

					for (int i = 0; i < 10; ++i)
					{
						AsteroidBelt.Asteroid newA = new AsteroidBelt.Asteroid();
						newA.Position = new Vector2(camera.Position.X + 1000.0f, -700.0f + (140.0f * i));
						newA.Rotation = RandomFloat(0, MathHelper.TwoPi);
						newA.Scale = RandomFloat(0.75f, 1.5f);
						newA.Sprite = topBelt.asteroidSprites[rnd.Next(topBelt.asteroidSprites.Count)];
						newA.Speed = (120.0f * Difficulty) * RandomFloat(0.75f, 1.5f);
						newA.Radius = ((float)Math.Sqrt((newA.Sprite.Width * newA.Sprite.Width) + (newA.Sprite.Height * newA.Sprite.Height))) * newA.Scale * 0.3f;
						asteroids.Add(newA);
					}
				}
				else
				{
					AsteroidBelt.Asteroid newA = new AsteroidBelt.Asteroid();
					newA.Position = new Vector2(camera.Position.X + 1000.0f, RandomFloat(-600.0f, 600.0f));
					newA.Rotation = RandomFloat(0, MathHelper.TwoPi);
					newA.Scale = RandomFloat(0.75f, 1.5f);
					newA.Sprite = topBelt.asteroidSprites[rnd.Next(topBelt.asteroidSprites.Count)];
					newA.Speed = (120.0f * Difficulty) * RandomFloat(0.75f, 1.5f);
					newA.Radius = ((float)Math.Sqrt((newA.Sprite.Width * newA.Sprite.Width) + (newA.Sprite.Height * newA.Sprite.Height))) * newA.Scale * 0.3f;
					asteroids.Add(newA);
				}
			}

			for (int i = 0; i < asteroids.Count; )
			{
				if (asteroids[i].Position.X > camera.Position.X - 1000.0f)
				{
					asteroids[i].Position.X -= asteroids[i].Speed * speedMod * dt;
					asteroids[i].Rotation -= 0.05f * dt;

					bool dead = false;

					if (playerShip.Invulnerable <= 0.0f)
					{
						if ((asteroids[i].Position - playerShip.Position).Length() <
							(playerShip.Radius + asteroids[i].Radius))
						{
							explostions.AddExplosion(asteroids[i].Position);
							explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();

							if (!playerShip.ShieldActive)
							{
								takeHitSfx.Play();
								playerShip.HullHealth -= 10.0f;
								playerShip.Invulnerable = 0.25f;
								speedMod = 4.0f;
							}

							asteroids.RemoveAt(i);
							dead = true;
						}
					}

					if (!dead)
						++i;
				}
				else
				{
					asteroids.RemoveAt(i);
				}
			}

#if DEBUG
			DebugDraw.Get.AddText("Asteroids: " + asteroids.Count.ToString());
#endif
		}

		private Random rnd = new Random();

		public float RandomFloat(float min, float max)
		{
			return min + (max - min) * (float)rnd.NextDouble();
		}

		private void KillAllInRange(Vector2 pos, float radius)
		{
			for (int j = 0; j < asteroids.Count; )
			{
				if ((asteroids[j].Position - pos).LengthSquared() <
					(radius + asteroids[j].Radius) * (radius + asteroids[j].Radius))
				{
					explostions.AddExplosion(asteroids[j].Position);
					explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
					asteroids.RemoveAt(j);
				}
				else
				{
					++j;
				}
			}

			for (int j = 0; j < enemyShips.Count; )
			{
				if ((enemyShips[j].Position - pos).LengthSquared() <
					(radius + enemyShips[j].Radius) * (radius + enemyShips[j].Radius))
				{
					ProcessAddingPickup(enemyShips[j].Position);
					explostions.AddExplosion(enemyShips[j].Position);
					explosionSfxs[rnd.Next(explosionSfxs.Count)].Play();
					enemyShips.RemoveAt(j);
				}
				else
				{
					++j;
				}
			}
		}
	}
}